<?php
/**
 * test case for Webappkit class
 * @author J.Ducastel <nospam0@ducastel.name>
 * @todo lasy-loading related tests
 */
class TestWebappkit extends UnitTestCase {

    /*function TestWebappkit() {
        $this->UnitTestCase('Testing Webappkit class');

        // $this->kit=webappkit::getKit('webappkit/tests');
        // $this->assertIsA($this->kit,'webappkit');
    }*/

    /**
     * here we use the webappkit tests kit itself as an exemple kit
     */
    function setUp() {

    }

    function tearDown() {

    }

    /**
    * @todo mergeArrays
    * @todo isVersionWithinRange
    * @todo listKits
    */
    function testUtilities() {
        $this->assertEqual(Webappkit::cmpVersionStrings('5.2.7','5.2.7'),0,"5.2.7 = 5.2.7");
        $this->assertEqual(Webappkit::cmpVersionStrings('5.2.*','5.2.7'),0,"5.2.* = 5.2.7");
        $this->assertEqual(Webappkit::cmpVersionStrings('5.*','5.2.7'),0);
        $this->assertEqual(Webappkit::cmpVersionStrings('5.2','4.2.9'),1);
        $this->assertEqual(Webappkit::cmpVersionStrings('4.2.9','5.2.7'),-1);
        $this->assertEqual(Webappkit::cmpVersionStrings('5.2.5','5.2'),1);
        $this->assertEqual(Webappkit::cmpVersionStrings('3.*','3.*'),0);
    }

    function testMergeArrays() {

        $default = array(
        'dblink'=>array(
            'host' => 'localhost'
            ,'db' => null
            ,'user' => 'root'
            , 'pwd' => null
            ,'encoding'=>null));

        $custom = array(
            'dblink'=>array(
                'user' => 'toto'
                ,'pwd' => 'secret'
                , 'db' => 'home')
            , 'custom' => 12
        );

        $result = array(
            'dblink' => array(
                'host' => 'localhost'
                , 'db' => 'home'
                , 'user' => 'toto'
                , 'pwd' => 'secret'
                , 'encoding' => null)
            , 'custom' => 12);

        $this->assertEqual(Webappkit::mergeArrays($default, $custom), $result);
    }


    function testStaticMethods() {
        try {
        $this->assertIsA(Webappkit::timecounter(),'float',"timecounter doesn't return a float");

        $this->assertTrue(Webappkit::checkKit('webappkit.testkit'));
        $this->assertFalse(Webappkit::checkKit('i/do/not/exist'));

        $this->assertIsA(Webappkit::checkId('webappkit.testkit'),'string');
        $this->assertFalse(Webappkit::checkId('with spaces'));
        } catch (Exception $e) {
            $this->fail("Exception should not have been raised with checkKit and checkId : ".$e->getMessage());
        }

        // version string
    }

    function testGetPathFromId() {
        $path=Webappkit::getPathFromId('webappkit.testkit');
        $this->assertIsA($path,'string',"getPathFromId shall return a string");
    }

    function testGetCfgFromId() {
        $cfg=Webappkit::getCfgFromId('webappkit.testkit');
        $this->assertIsA($cfg,'WakKitCfg',"getCfgFromId shall return a WakKitCfg instance");
        // exceptions
        try {
            $cfg=Webappkit::getCfgFromId('webappkit.testkit.badkit1');
            $this->fail("getCfgFromId shall raise WakBadCfg when no/bad cfg");
        } catch (WakBadCfg $e) {
            $this->pass("getCfgFromId shall raise WakBadCfg when no/bad cfg");
        } catch (Exception $e) {
            $this->fail("getCfgFromId shall raise WakBadCfg when no/bad cfg");
        }
        try {
            $cfg=Webappkit::getCfgFromId('webappkit.testkit.badkit5');
            $this->fail("getCfgFromId shall raise WakBadCfg when no/bad cfg");
        } catch (WakBadCfg $e) {
            $this->pass("getCfgFromId shall raise WakBadCfg when no/bad cfg");
        } catch (Exception $e) {
            $this->fail("getCfgFromId shall raise WakBadCfg when no/bad cfg");
        }
    }

    /**
     * test kit version range requiring
     */
    function testVersion() {
        try {
            $msg="loadKit(id,version_range) shall raise WakBadVersion if version range don't match available version";
            Webappkit::loadKit('webappkit.testkit.version1','2+');
            $this->fail($msg);
        } catch (WakBadVersion $e) {
            $this->pass($msg);
        }
        try {
            $msg="loadKit() shall raise WakMissingKit if kit requires another kit in unavailable available version";
            Webappkit::loadKit('webappkit.testkit.badkit7');
            $this->fail($msg);
        } catch (WakMissingKit $e) {
            $this->pass($msg);
        }
    }

    // should be before testlibkit
    function testGetKit() {
        try {
            $kit=&Webappkit::getKit('webappkit.testkit');
            // class
            $this->assertIsA($kit,'RunKit',"testkit should have custom RunKit class");
            // loaded subkits
            // deactivated because admin loads kits+subkits at the moment, for diagnostics
            $this->assertFalse(class_exists('someclass'),"SHOULD NOT have loaded optional subkit");
            // tools
            $this->assertIsA($kit->test,'WakTool',"testkit should have a 'test' tool");
        } catch (Exception $e) {
            $this->fail("should not have raised exception at this point");
        }

        // exceptions
        try {
            Webappkit::getKit('i am not a kit');
            Webappkit::getKit('i/am/not/a/kit/either');
            $this->fail("getkit should raise a WakBadKit exception on invalid ids");
        } catch (WakBadKit $e) {
            $this->pass("getkit should raise a WakBadKit exception on invalid ids");
        }
        try {
            // wak.ini missing
            Webappkit::getKit('webappkit.testkit.badkit1');
            $this->fail("getkit shall raise WakBadCfg if wak.ini is missing %s");
        } catch (WakBadCfg $e) {
            $this->pass("getkit shall raise WakBadCfg if wak.ini is missing %s");
        }
        try {
            // kit class missing
            Webappkit::getKit('webappkit.testkit.badkit2');
            $this->fail("getkit should raise WakBadKit if kit class is missing");
        } catch (WakBadKit $e) {
            $this->pass();
        }
        try {
            // kit class not extending webappkit
            Webappkit::getKit('webappkit.testkit.badkit3');
            $this->fail("getkit should raise WakBadKit if kit class dont extend webappkit");
        } catch (WakBadKit $e) {
            $this->pass();
        }
        // missing kits
        try {
            Webappkit::loadKit('webappkit.testkit.badkit4');
            $this->fail("loadkit should raise WakMissingKit if kit requires missing kits");
        } catch (WakMissingKit $e) {
            $this->pass();
        }
        // missing files
        try {
            Webappkit::loadKit('webappkit.testkit.badkit6');
            $this->fail("loadkit should raise WakMissingFile if kit requires missing files");
        } catch (WakMissingFile $e) {
            $this->pass();
        }
    }

    function testLibKit() {
        try  {
            $version=Webappkit::loadKit('webappkit.testkit.libkit');
            $this->assertIsA($version,'string',"loadKit should return version loaded. %s");

            // checking loaded files
            $this->assertTrue(class_exists('someclass'),"should have loaded someclass library file");
            $this->assertEqual(SomeClass::php(),5);

            // testing run
            $kit=Webappkit::getKit('webappkit.testkit.libkit');
            $kit->run();
            $this->fail("kit->run should raise WakNotImplemented by default");
        } catch (WakNotImplemented $e) {
            $this->pass("kit->run should raise WakNotImplemented by default");
        } catch (Exception $e) {
            $this->fail($e->getMessage());
        }

    }

    function testConstructor() {
        $kit=&Webappkit::getkit('webappkit.testkit');
        $this->assertIsA($kit,'WakKit');

        $kit2=&Webappkit::getkit('webappkit.testkit');
        $this->assertReference($kit,$kit2,"Kits should be singletons ! %s");

        $kit3=&Webappkit::getkit('webappkit/testkit');
        $this->assertReference($kit,$kit3,"Kits should be singletons, using both / or dot level separators ! %s");

        // checking class

        // checking tools

        // $this->expectError();
    }

    function testInstanceMethods() {
        $id='webappkit.testkit';
        try {

            $kit=&Webappkit::getkit($id);

            $this->assertEqual($kit->getId(),$id);

            $path=$kit->getPath($id);
            $this->assertIsA($path,'string',"invalid path %s");
            $this->assertTrue(file_exists($path),"path doesn't exist. ($path)");

            $this->assertIsA($kit->getCfg(),'WakKitCfg');
        } catch (Exception $e) {
            $this->fail($e->getMessage());
        }
    }

    /**
     * webappkit.testkit should have 2 tools
     */
    function testGetTools() {
        $id='webappkit.testkit';
        try {

            $kit=&Webappkit::getkit($id);
            $tools=$kit->getTools();
            $this->assertEqual(count($tools),2
                ,"webappkit.testkit have 2 tools that should be returned by getTools()");
            $this->assertIsA($tools['test'],'WakTool'
                ,"getTools() shall return an associative array of instances");
            // filtering
            $tools=$kit->getTools('WakStorage');
            $this->assertEqual(count($tools),1
                ,"getTools(of_class) shall return only tools of specified class");
            $this->assertIsA($tools['teststorage'],'WakStorage'
                ,"getTools() shall return an associative array of instances");
            // $this->dump($kit);
        } catch (Exception $e) {
            $this->fail($e->getMessage());
        }
    }

    function testExceptions() {



    }

    /*function testFail() {
        $this->assertTrue(false);
        $this->assertError();
        $this->assertTrue(trigger_error("une erreur"));
    }*/

}
